home *** CD-ROM | disk | FTP | other *** search
- /*
- * @(#)inline.c 1.7 9/24/87
- */
- #include "assert.h"
- #include "error.h"
- #include "ident.h"
- #include "nodes.h"
- #include "builtins.h"
- #include "sequence.h"
- #include "system.h"
- #include "trace.h"
- #include "opNames.h"
- #include "option.h"
-
- /*
- * inline's job is to decide if operations are inline-able, and set their
- * isInLineAble bit in the b.opdef. It also finds monitored operations
- * where signals happen as the last thing and sets the useSignalAndExit bit
- * in b.signalstat. It is also supposed to find objects that have monitors where
- * the monitor can be elided.
- */
-
- int countStatements(p)
- NodePtr p;
- {
- register NodePtr q;
- register int thisCount = 0;
-
- if ((int) p <= 0x200) return(0);
- switch (p->tag) {
- case P_ASSIGNSTAT:
- case P_ASSERTSTAT:
- case P_FIXSTAT:
- case P_REFIXSTAT:
- case P_UNFIXSTAT:
- case P_MOVESTAT:
- case P_PRIMSTAT:
- case P_WAITSTAT:
- case P_SIGNALSTAT:
- case P_VARDECL:
- case P_CONSTDECL:
- case P_EXITSTAT:
- case P_CHECKPOINTSTAT:
- case P_RETURNSTAT:
- case P_RETURNANDFAILSTAT:
- return(1);
- case P_IFSTAT:
- thisCount = 1;
- break;
- default:
- break;
- }
- Sequence_For(q, p)
- thisCount += countStatements(q);
- Sequence_Next
- return(thisCount);
- }
-
- int countNodes(p)
- NodePtr p;
- {
- register NodePtr q;
- register int thisCount = 1;
-
- if ((int) p <= 0x200) return(0);
- Sequence_For(q, p)
- thisCount += countNodes(q);
- Sequence_Next
- return(thisCount);
- }
-
- #define INLINENODELIMIT 30
- #define INLINESTATEMENTLIMIT 3
-
- typedef struct sFSRec {
- NodePtr signals;
- Boolean isStatement;
- } FSRec, *FSRecPtr;
-
- FSRec findTerminalSignals(p)
- NodePtr p;
- {
- register NodePtr q, r;
- FSRec myResult, hisResult;
- myResult.isStatement = FALSE;
- myResult.signals = NULL;
-
- if ((int) p <= 0x200) return(myResult);
- switch (p->tag) {
- case P_FAILUREHANDLER:
- case P_UNAVAILABLEHANDLER:
- break;
- case P_BLOCK:
- return(findTerminalSignals(p->b.block.stats));
- case T_SEQUENCE:
- Sequence_For(q, p)
- hisResult = findTerminalSignals(q);
- /* merge the results */
- if (hisResult.isStatement) {
- Free(myResult.signals);
- myResult.signals = NN;
- }
- Sequence_For(r, hisResult.signals)
- Sequence_Add(&myResult.signals, r);
- Sequence_Next
- Free(hisResult.signals);
- Sequence_Next
- break;
- case P_IFSTAT:
- myResult.isStatement = TRUE;
- Sequence_For(q, p->b.ifstat.ifclauses)
- hisResult = findTerminalSignals(q->b.ifclause.stats);
- Sequence_For(r, hisResult.signals)
- Sequence_Add(&myResult.signals, r);
- Sequence_Next
- Free(hisResult.signals);
- Sequence_Next
- if ((q = p->b.ifstat.elseclause) != NN) {
- hisResult = findTerminalSignals(q->b.elseclause.stats);
- Sequence_For(r, hisResult.signals)
- Sequence_Add(&myResult.signals, r);
- Sequence_Next
- Free(hisResult.signals);
- }
- break;
- case P_IFCLAUSE:
- case P_ELSECLAUSE:
- break;
- case P_LOOPSTAT:
- case P_ASSIGNSTAT:
- case P_ASSERTSTAT:
- case P_REFIXSTAT:
- case P_FIXSTAT:
- case P_UNFIXSTAT:
- case P_MOVESTAT:
- case P_PRIMSTAT:
- case P_WAITSTAT:
- case P_VARDECL:
- case P_CONSTDECL:
- case P_EXITSTAT:
- case P_CHECKPOINTSTAT:
- myResult.isStatement = TRUE;
- break;
- case P_RETURNSTAT:
- case P_RETURNANDFAILSTAT:
- myResult.isStatement = FALSE;
- break;
- case P_SIGNALSTAT:
- myResult.isStatement = TRUE;
- Sequence_Add(&myResult.signals, p);
- break;
- default:
- break;
- }
- return (myResult);
- }
-
- static int compareImports(left, right)
- NodePtr *left, *right;
- {
- NodePtr l, r;
- l = (*left)->b.setq.outer;
- r = (*right)->b.setq.outer;
- if (l->tag != P_SYMREF) return(-1);
- if (r->tag != P_SYMREF) return(1);
- return(l->b.symref.symbol->itsSymbolNumber -
- r->b.symref.symbol->itsSymbolNumber);
- }
-
- extern Boolean isARealImport();
-
- static Boolean doImportsMatch(sig, obj)
- register NodePtr sig, obj;
- {
- Symbol importedSym, aParam;
- register NodePtr import;
- register int nextParam = 0;
-
- TRACE2(imports, 1, "Checking object %s against signature %s",
- ATName(obj), SigName(sig));
- Sequence_For(import, obj->b.oblit.setq)
- if (isARealImport(import->b.setq.inner->b.symdef.symbol, FALSE)) {
- if (import->b.setq.outer->tag != P_SYMREF) return(FALSE);
- importedSym = import->b.setq.outer->b.symdef.symbol;
- if (nextParam >= Sequence_Length(sig->b.opsig.params)) return(FALSE);
- aParam = sig->b.opsig.params->b.children[nextParam]->b.param.sym->b.symdef.symbol;
- TRACE2(imports, 1, "Symbol %s must match %s", STName(importedSym),
- STName(aParam));
- if (aParam == importedSym) {
- nextParam ++;
- TRACE0(imports, 1, "yes!");
- } else {
- TRACE0(imports, 1, "no!\nReturning FALSE");
- return(FALSE);
- }
- }
- Sequence_Next
- TRACE0(imports, 1, "Returning TRUE");
- return(TRUE);
- }
-
- extern void DisplayTree();
-
- checkWonderfullyImmutable(p)
- NodePtr p;
- {
- if (p->b.oblit.process != NN) {
- ErrorMessage(p, "Immutable objects may not contain processes");
- }
- if (p->b.oblit.monitor != NN &&
- !p->b.oblit.monitor->b.monitor.mayBeElided &&
- Sequence_Length(p->b.oblit.monitor->b.monitor.decls) != 0 &&
- Sequence_Length(p->b.oblit.monitor->b.monitor.ops) != 0) {
- ErrorMessage(p, "Immutable objects may not contain monitors");
- }
- }
-
- void detectInlines(p)
- NodePtr p;
- {
- register NodePtr q;
- FSRec andExitableSignals;
- register Boolean isInlineable = TRUE;
- Boolean done = FALSE;
-
- if ((int) p <= 0x200) return;
- switch (p->tag) {
- case P_CONSTDECL:
- if (p->b.constdecl.sym->b.symdef.symbol->isManifest) {
- detectInlines(p->b.constdecl.sym->b.symdef.symbol->value.value);
- done = TRUE;
- }
- break;
- case P_INVOC:
- default:
- break;
- }
- if (!done) Sequence_For(q, p)
- if ((int)q > 0x200) detectInlines(q);
- Sequence_Next
- switch (p->tag) {
- case P_OBLIT:
- if (! p->b.oblit.f.isTypeVariable &&
- ! p->b.oblit.f.dependsOnTypeVariable &&
- ! p->b.oblit.f.isManifest) {
- if (Sequence_Length(p->b.oblit.setq) > 1) {
- IFTRACE(imports, 1) {
- trace(1, "Sorting imports of %s", ATName(p));
- trace(1, "Before:");
- DisplayTree(stdout, p->b.oblit.setq, 0, 999);
- }
- qsort((char *)&(p->b.oblit.setq->b.children[0]),
- Sequence_Length(p->b.oblit.setq),
- sizeof(NodePtr),
- compareImports);
- IFTRACE(imports, 1) {
- trace(1, "After:");
- DisplayTree(stdout, p->b.oblit.setq, 0, 999);
- }
- }
- }
- if (p->b.oblit.f.immutable) {
- checkWonderfullyImmutable(p);
- }
- break;
-
- case P_OPDEF:
- #define PESSIMISTIC
- #ifdef PESSIMISTIC
- q = p->b.opdef.body;
- if (q->b.block.failurehandler != NN) isInlineable = FALSE;
- else if (q->b.block.unavailablehandler != NN) isInlineable = FALSE;
- else {
- q = q->b.block.stats;
- if (Sequence_Length(q) != 1) isInlineable = FALSE;
- else if (q->b.children[0]->tag == P_PRIMSTAT) isInlineable = TRUE;
- else if (q->b.children[0]->tag == P_ASSIGNSTAT) {
- q = q->b.children[0];
- if (Sequence_Length(p->b.opdef.sig->b.opsig.results) != 1) isInlineable = FALSE;
- else if (q->b.assignstat.right->nChildren != 1) isInlineable = FALSE;
- else if (q->b.assignstat.left->nChildren != 1) isInlineable = FALSE;
- else if (q->b.assignstat.right->b.children[0]->tag == P_OBLIT) {
- isInlineable = doImportsMatch(p->b.opdef.sig,
- q->b.assignstat.right->b.children[0]);
- } else IFOPTION(inline, 1) {
- isInlineable = TRUE;
- } else {
- isInlineable = FALSE;
- }
- } else {
- isInlineable = FALSE;
- }
- }
- p->b.opdef.isInlineable = isInlineable;
- #else
- if (countNodes(p) <= INLINENODELIMIT && countStatements(p) <= INLINESTATEMENTLIMIT) {
- p->b.opdef.isInlineable = TRUE;
- }
- #endif
- andExitableSignals = findTerminalSignals(p->b.opdef.body);
- Sequence_For(q, andExitableSignals.signals)
- assert(q->tag == P_SIGNALSTAT);
- q->b.signalstat.useSignalAndExit = TRUE;
- Sequence_Next
- Free(andExitableSignals.signals);
- break;
- default:
- break;
- }
- }
-